diff options
Diffstat (limited to 'src/core/file_sys/fssystem/fssystem_switch_storage.h')
-rw-r--r-- | src/core/file_sys/fssystem/fssystem_switch_storage.h | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/core/file_sys/fssystem/fssystem_switch_storage.h b/src/core/file_sys/fssystem/fssystem_switch_storage.h new file mode 100644 index 000000000..2b43927cb --- /dev/null +++ b/src/core/file_sys/fssystem/fssystem_switch_storage.h @@ -0,0 +1,80 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/file_sys/fssystem/fs_i_storage.h" + +namespace FileSys { + +class RegionSwitchStorage : public IReadOnlyStorage { + YUZU_NON_COPYABLE(RegionSwitchStorage); + YUZU_NON_MOVEABLE(RegionSwitchStorage); + +public: + struct Region { + s64 offset; + s64 size; + }; + +public: + RegionSwitchStorage(VirtualFile&& i, VirtualFile&& o, Region r) + : m_inside_region_storage(std::move(i)), m_outside_region_storage(std::move(o)), + m_region(r) {} + + virtual size_t Read(u8* buffer, size_t size, size_t offset) const override { + // Process until we're done. + size_t processed = 0; + while (processed < size) { + // Process on the appropriate storage. + s64 cur_size = 0; + if (this->CheckRegions(std::addressof(cur_size), offset + processed, + size - processed)) { + m_inside_region_storage->Read(buffer + processed, cur_size, offset + processed); + } else { + m_outside_region_storage->Read(buffer + processed, cur_size, offset + processed); + } + + // Advance. + processed += cur_size; + } + + return size; + } + + virtual size_t GetSize() const override { + return m_inside_region_storage->GetSize(); + } + +private: + bool CheckRegions(s64* out_current_size, s64 offset, s64 size) const { + // Check if our region contains the access. + if (m_region.offset <= offset) { + if (offset < m_region.offset + m_region.size) { + if (m_region.offset + m_region.size <= offset + size) { + *out_current_size = m_region.offset + m_region.size - offset; + } else { + *out_current_size = size; + } + return true; + } else { + *out_current_size = size; + return false; + } + } else { + if (m_region.offset <= offset + size) { + *out_current_size = m_region.offset - offset; + } else { + *out_current_size = size; + } + return false; + } + } + +private: + VirtualFile m_inside_region_storage; + VirtualFile m_outside_region_storage; + Region m_region; +}; + +} // namespace FileSys |